class GameView extends eui.Component implements  eui.UIComponent {
	public scoreLbl:eui.Label;
	public numItems:CentralView;
	public touchRect:eui.Rect;
	public startBtn:eui.Button;
	public startBtnLbl:eui.Label;
	public backBtn:eui.Button;
	public backGroup:eui.Group;
	public returnBtn:eui.Button;
	public historyScoreLbl:eui.Label;

	private gameData:Array<number[]>;
	private gameDataLast:Array<Array<number[]>>;
	private lastDataLen:number;
	private moveTimer:egret.Timer;
	private isWin:boolean;
	private maxScore:number = 0;

	private backFreeTime:number;
	private static MAX_LAST_LEN:number = 5;

	public constructor() {
		super();

		this.addEventListener(eui.UIEvent.COMPLETE, this.onComplete, this);
		this.skinName = "resource/game/GameView.exml";
	}

	protected partAdded(partName:string,instance:any):void
	{
		super.partAdded(partName,instance);
	}

	protected childrenCreated():void
	{
		super.childrenCreated();
	}

	private onComplete(event:Event)
	{
		this.touchRect.addEventListener(egret.TouchEvent.TOUCH_BEGIN, this.onTouchBegin, this);
		this.touchRect.addEventListener(egret.TouchEvent.TOUCH_END, this.onTouchEnd, this);
		this.startBtn.addEventListener(egret.TouchEvent.TOUCH_TAP, this.onStartBtn, this);
		this.backBtn.addEventListener(egret.TouchEvent.TOUCH_TAP, this.onBackBtn, this);
		this.returnBtn.addEventListener(egret.TouchEvent.TOUCH_TAP, this.onReturnBtn, this);
		this.moveTimer = new egret.Timer(CentralView.MOVETIME + 50);
		this.moveTimer.addEventListener(egret.TimerEvent.TIMER_COMPLETE, this.onMoveEnd, this);

		this.initGame();
		this.getStorage();
	}

	private touchX:number;
	private touchY:number;
	private onTouchBegin(event:egret.TouchEvent)
	{
		//console.log(event.localX + ", " + event.localY);
		this.touchX = event.localX;
		this.touchY = event.localY;
	}
	private onTouchEnd(event:egret.TouchEvent)
	{
		//console.log(event.localX + ", " + event.localY);
		let x = event.localX;
		let y = event.localY;
		if (this.touchX == x && this.touchY == y)
			return;

		this.insertLastData();

		// calc position
		let left_right = x - this.touchX > 0 ? MainLogic.RIGHT : MainLogic.LEFT;
		let up_down = y - this.touchY > 0 ? MainLogic.DOWN : MainLogic.UP;
		let position = 0;
		if (Math.abs(x - this.touchX) > Math.abs(y - this.touchY))
		{
			position = left_right;
		}
		else
		{
			position = up_down;
		}
		//this.print_gameData();
		let move_table:Array<number[]> = new Array<number[]>();	// 用于移动的动画，数字表示需要移动到的位置，如往下移动则0表示当前移动到最下面的格子
		let comb_table:Array<number[]> = new Array<number[]>();	// 用于缩放的动画，需要显示缩放的值为1
		let ret_array:Array<number> = new Array<number>();		// 用于move返回值，[0]是是否失败，[1]是是否胜利
		let ismove:boolean = MainLogic.move(this.gameData, position, move_table, comb_table, ret_array);	// 计算移动
		this.numItems.move(move_table, position, comb_table);	// 移动动画
		//this.print_gameData();

		if (ismove)
		{
			let num:number = Number(this.scoreLbl.text);
			for (let i = 0; i < 4; i++)
			{
				for (let j = 0; j< 4; j++)
				{
					if (comb_table[i][j] == 1)
						num += 2;
				}
			}
			this.scoreLbl.text = "" + num;	// 设置积分

			this.moveTimer.repeatCount = 1;
			this.moveTimer.start();			// 等移动完之后设置正确的数据

			this.setStorage();
			SoundManager.getInstance().playMove();
		}
		else
		{
			this.removeLastData();
		}
		if (ret_array[1] == 1 && !this.isWin)
		{
			this.addChild(new MessageView("WIN", "居然玩到了2048，恭喜你，你赢了！", false));
			this.isWin = true;
		}
		else if (ret_array[0] == 1)
		{
			this.addChild(new MessageView("FAIL", "(⊙o⊙)… 你输了哦，再接再厉吧！", false));
		}
	}

	private onMoveEnd()
	{
		this.moveTimer.stop();
		
		this.numItems.showData(this.gameData);
		this.numItems.resetPosition();
		this.numItems.scaleNum();
	}

	public initGame()
	{
		this.gameData = new Array<number[]>();
		this.gameData[0] = new Array<number>();
		this.gameData[1] = new Array<number>();
		this.gameData[2] = new Array<number>();
		this.gameData[3] = new Array<number>();
		for (let i = 0; i < 4; i++)
		{
			for (let j = 0; j < 4; j++)
			{
				this.gameData[i][j] = MainLogic.getRandom(0, 2) == 0 ? 2 : 0;
				//this.gameData[i][j] = Math.pow(2, (i + j)+ 4);
			}
		}
		//this.gameData[3][3] = 0;

		this.numItems.showData(this.gameData);
		this.scoreLbl.text = "0";
		this.isWin = false;
		this.gameDataLast = new Array<Array<number[]>>();
		this.backGroup.visible = true;
		this.lastDataLen = 0;
		this.backFreeTime = 2;
		this.startBtnLbl.text = "restart";
		//this.print_gameData();
	}

	private onStartBtn()
	{
		if (this.startBtnLbl.text == "restart")
		{
			this.addChild(new MessageView("NOTE", "确定重新开始游戏？将会清空当前数据！", true, this.onRestartConfirm, this));
			return;
		}
		
		this.initGame();
		this.startBtnLbl.text = "restart";
	}

	private onBackBtn()
	{
		if (this.backFreeTime <= 0)
			this.addChild(new MessageView("NOTE", "是否扣除50积分后退一步？", true, this.onBackConfirm, this));
		else
			this.addChild(new MessageView("NOTE", "本次还剩" + this.backFreeTime + "次免费次数，确定后退一步？", true, this.onBackConfirm, this));
	}

	private onRestartConfirm()
	{
		this.initGame();
		this.setStorage();
	}

	private onBackConfirm()
	{
		if (this.lastDataLen > 0)
		{
			let score = parseInt(this.scoreLbl.text);
			if (this.backFreeTime <= 0 && score < 50)
			{
				this.addChild(new MessageView("NOTE", "o(╥﹏╥)o 积分不足无法后退一步！", false));
			}
			else
			{
				if (this.backFreeTime > 0)
				{
					this.backFreeTime--;
				}
				else if (score >= 50)
				{
					this.scoreLbl.text = "" + (score - 50);
				}
				this.copyDataToCurr(this.gameDataLast[this.lastDataLen - 1]);
				this.removeLastData();
				this.numItems.showData(this.gameData);
				this.setStorage();
			}
		}
		else
		{
			this.addChild(new MessageView("NOTE", "无法后退，已经后退到最后一步了！", false));
		}
	}

	private insertLastData()
	{
		let index = this.lastDataLen;
		this.gameDataLast[index] = new Array<number[]>();
		for (let i = 0; i < 4; i++)
		{
			this.gameDataLast[index][i] = new Array<number>();
			for (let j = 0; j < 4; j++)
			{
				this.gameDataLast[index][i][j] = this.gameData[i][j];
			}
		}
		this.lastDataLen++;
		while (this.lastDataLen > GameView.MAX_LAST_LEN)
		{
			this.gameDataLast.splice(0, 1);
			this.lastDataLen--;
		}
	}

	private removeLastData()
	{
		let index = this.lastDataLen - 1;
		if (index >= 0)
		{
			this.gameDataLast.pop();
			this.lastDataLen--;
		}
	}

	private copyDataToCurr(data:Array<number[]>)
	{
		for (let i = 0; i < 4; i++)
		{
			for (let j = 0; j < 4; j++)
			{
				this.gameData[i][j] = data[i][j];
			}
		}
	}

	private print_gameData()
	{
		console.log("gameData:")
		for (let i = 0; i < 4; i++)
		{
			console.log(this.gameData[i][0] + ", " + this.gameData[i][1] + ", " + this.gameData[i][2] + ", " + this.gameData[i][3])
		}
	}

	private onReturnBtn()
	{
		this.parent.removeChild(this);
	}

	private setStorage()
	{
		let str = MainLogic.getStorageString(this.gameData);
		egret.localStorage.setItem("currData", str);
		egret.localStorage.setItem("isWin", this.isWin ? "1" : "0");
		egret.localStorage.setItem("backFreeTime", "" + this.backFreeTime);

		let last_str = MainLogic.getLastStorageString(this.gameDataLast, this.lastDataLen);
		egret.localStorage.setItem("lastData", last_str);
		egret.localStorage.setItem("lastDataLen", "" + this.lastDataLen);
		egret.localStorage.setItem("score", this.scoreLbl.text);

		let maxscore = parseInt(this.scoreLbl.text)
		if (maxscore > this.maxScore)
		{
			this.maxScore = maxscore;
			egret.localStorage.setItem("maxscore", "" + this.maxScore);
			let maxstr = MainLogic.getStorageString(this.gameData);
			egret.localStorage.setItem("maxscoredata", maxstr);
			this.historyScoreLbl.text = "" + maxscore;
		}
	}

	private getStorage()
	{
		let currDataStr = egret.localStorage.getItem("currData");
		if (currDataStr)
		{
			this.copyDataToCurr(MainLogic.getStorageData(currDataStr));

			let str = egret.localStorage.getItem("lastDataLen");
			if (str)
				this.lastDataLen = parseInt(str);

			let lastDataStr = egret.localStorage.getItem("lastData");
			if (lastDataStr)
				this.gameDataLast = MainLogic.getLastStorageData(lastDataStr, this.lastDataLen);

			str = egret.localStorage.getItem("isWin");
			if (str)
				this.isWin = str == "1" ? true : false;

			str = egret.localStorage.getItem("backFreeTime");
			if (str)
				this.backFreeTime = str ? parseInt(str) : 0;

			str = egret.localStorage.getItem("score");
			if (str)
				this.scoreLbl.text = str;

			str = egret.localStorage.getItem("maxscore");
			if (str)
			{
				this.maxScore = parseInt(str);
				this.historyScoreLbl.text = "" + this.maxScore;
			}
			
			this.startBtnLbl.text = "restart";
		}

		this.numItems.showData(this.gameData);
	}
	
}